/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package intopo.evogame.partnerselection.population;

import intopo.evogame.partnerselection.config.ConstructStrategyException;
import intopo.evogame.partnerselection.config.ParsingException;
import intopo.evogame.partnerselection.config.TagException;
import intopo.evogame.partnerselection.chromosome.Chromosome;
import intopo.evogame.partnerselection.chromosome.ChromosomeFactory;
import intopo.evogame.partnerselection.chromosome.ChromosomeGenerator;
import intopo.evogame.partnerselection.config.AbstractTextConfigFile;
import intopo.evogame.partnerselection.player.AbstractPlayer;
import intopo.evogame.partnerselection.player.PlayerFactory;
import intopo.game.Strategy;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

/**
 * An unordered collection of players.
 * 
 * @author <a href="mailto:mariano.pedro@gmail.com">Pedro Mariano</a>
 *
 * @version 1.0 
 */
final public class PlayerCollection<
		  S extends Strategy<S>,
		  C extends Chromosome<S>,
		  P extends AbstractPlayer<S, C, P>>
	implements Iterable<P>
{
	/**
	 * The set of players in this collection.
	 */
	final protected Set<P> players;
//	/**
//	 * Construct an empty collection of players
//	 */
//	protected PlayerCollection ()
//	{
//		this.players = new HashSet<P> ();
//	}
//	/**
//	 * Construct a collection of players using the chromosomes given by {@code generator}
//	 * @param generator The chromosome generator.
//	 * @param factory The player factory.
//	 */
//	protected PlayerCollection (ChromosomeGenerator<S, C> generator, PlayerFactory<S, C, P> factory)
//	{
//		this.players = new HashSet<P> ();
//		int howMany = generator.size ();
//		while (howMany > 0) {
//			C chromosome = generator.next ();
//			this.players.add (factory.create (chromosome));
//		}
//	}

	/**
	 * 
	 * @param scanner
	 * @param playerFactory
	 * @param chromosomeFactory
	 * @param map
	 * @throws java.io.IOException
	 * @throws intopo.evogame.partnerselection.config.TagException
	 * @throws intopo.evogame.partnerselection.config.ConstructStrategyException
	 * @throws intopo.evogame.partnerselection.config.ParsingException
	 */
	protected PlayerCollection (Scanner scanner, PlayerFactory<S, C, P> playerFactory, ChromosomeFactory<S, C> chromosomeFactory, Map<String, Constructor<? extends S>> map, Node<S, C, P> node)
		throws
			IOException,
			TagException,
			ConstructStrategyException,
			ParsingException
	{
		this.players = new HashSet<P> ();
		int numberEntries = AbstractTextConfigFile.readInt (scanner, "Number of entries");
		while (numberEntries > 0) {
			int howMany = scanner.nextInt ();
			C c = chromosomeFactory.create (scanner, map);
			while (howMany > 0) {
				this.players.add (playerFactory.create (c, node, 0));
				howMany--;
			}
			numberEntries--;
		}
	}

	protected PlayerCollection ()
	{
		this.players = new HashSet<P> ();
	}
	final void add (P p)
	{
		this.players.add (p);
	}
	final void remove (P p)
	{
		this.players.remove (p);
	}
	final int size ()
	{
		return this.players.size ();
	}
	/**
	 * Return an iterator over the players in this population.  Insertion and removal of players does not change the order of returned players.
	 * @return an iterator over the players in this population
	 */
	@Override
	final public Iterator<P> iterator ()
	{
		return this.players.iterator ();
//		return new ReadOnlyIterator<S, C, P> (this);
	}
	/**
	 * A read-only iterator over the players in the enclosing collection.
	 * @param <S> Strategy type used by the players.
	 * @param <C> Chromosome type that represents the player's chromosome.
	 * @param <P> Player type.
	 */
	static private class ReadOnlyIterator<
		  S extends Strategy<S>,
		  C extends Chromosome<S>,
		  P extends AbstractPlayer<S, C, P>>
		implements Iterator<P>
	{
		/**
		 * The backing iterator used to access the players in the enclosing collection.
		 */
		private Iterator<P> iterator;
		/**
		 * Construct a read-only iterator over the collection of players {@code players}
		 * @param players  The collection of players that this iterator is using.
		 */
		ReadOnlyIterator (PlayerCollection<S, C,P> players)
		{
			this.iterator = players.players.iterator ();
		}
		@Override
		public boolean hasNext ()
		{
			return this.iterator.hasNext ();
		}
		@Override
		public P next ()
		{
			return this.iterator.next ();
		}
		@Override
		public void remove ()
		{
			throw new UnsupportedOperationException ("Read-only iterator");
		}

	}
}

// Local Variables:
// mode: java
// mode: flyspell-prog
// ispell-local-dictionary: "british"
// End:
